from flask import Flask, render_template, request, url_for, jsonify
from datetime import timedelta
from dbkit import Database
import math

app = Flask(__name__)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)
app.jinja_env.auto_reload = True

dbName = 'company.db'
dbkit = Database()
dbkit.key("企业名称")


@app.route('/', methods=['GET'])
def page_index():
    return render_template('index.html')


@app.route('/login', methods=['POST'])
def page_login():
    if request.method == 'POST':
        print("signalLogin received!")
        data = request.get_json()
        print(data)
        username = data[0]
        password = data[1]
        dbkit.open(dbName)
        dbkit.key("用户名")
        account = dbkit.getCells("账户", expr="[用户名]='" + username + "'")
        if len(account) == 0:
            data = "Invalid"
        else:
            account = account[0]
            if account[1] == password:
                if account[2] == True or account[2] == 'TRUE':
                    data = "Admin"
                else:
                    data = "Success"
            else:
                data = "Wrong"
        dbkit.close()
        print("slotLogin triggering...")
        print(data)
        return data


@app.route('/register', methods=['POST'])
def page_register():
    if request.method == 'POST':
        print("signalRegister received!")
        data = request.get_json()
        print(data)
        username = data[0]
        password = data[1]
        dbkit.open(dbName)
        dbkit.key("用户名")
        account = dbkit.getCells("账户", expr="[用户名]='" + username + "'")
        if len(account) == 0:
            dbkit.addRow("账户", username)
            dbkit.fillCell("账户", username, "密码", password)
            dbkit.db.commit()
            account = dbkit.getCells("账户", expr="[用户名]='" + username + "'")
            if len(account) > 1:
                data = "Success"
            else:
                data = "Failure"
        else:
            data = "Conflict"
        dbkit.close()
        print("slotRegister triggering...")
        print(data)
        return data


specialField = ["企业(机构)类型", "企业类别", "行业门类", "目前状态"]  # 2,3,4,5
fieldIndex = {"企业(机构)类型": 0, "企业类别": 1, "行业门类": 2, "目前状态": 3}
mapByKey = [
    [
        "",
        "一人有限责任公司",
        "一人有限责任公司分公司",
        "个人独资企业",
        "个人独资企业分支机构",
        "全民所有制",
        "全民所有制分支机构(非法人)",
        "其他有限责任公司",
        "其他有限责任公司分公司",
        "其他股份有限公司(非上市)",
        "其他股份有限公司分公司(上市)",
        "其他股份有限公司分公司(非上市)",
        "内资分公司",
        "农民专业合作经济组织",
        "外商投资企业分公司",
        "外商投资合伙企业分支机构",
        "普通合伙企业",
        "普通合伙企业分支机构",
        "有限合伙企业",
        "有限合伙企业分支机构",
        "有限责任公司",
        "有限责任公司(中外合资)",
        "有限责任公司(台港澳与境内合资)",
        "有限责任公司(台港澳合资)",
        "有限责任公司(台港澳法人独资)",
        "有限责任公司(台港澳自然人独资)",
        "有限责任公司(国有控股)",
        "有限责任公司(国有独资)",
        "有限责任公司(外商投资企业与内资合资)",
        "有限责任公司(外商投资企业法人独资)",
        "有限责任公司(外国法人独资)",
        "有限责任公司(外国自然人独资)",
        "有限责任公司(自然人投资或控股)",
        "有限责任公司(自然人投资或控股的法人独资)",
        "有限责任公司(自然人独资)",
        "有限责任公司(非自然人投资或控股的法人独资)",
        "有限责任公司分公司",
        "有限责任公司分公司(国有控股)",
        "有限责任公司分公司(国有独资)",
        "有限责任公司分公司(外商投资企业与内资合资)",
        "有限责任公司分公司(外商投资企业合资)",
        "有限责任公司分公司(外商投资企业投资)",
        "有限责任公司分公司(外商投资企业法人独资)",
        "有限责任公司分公司(自然人投资或控股)",
        "有限责任公司分公司(自然人投资或控股的法人独资)",
        "有限责任公司分公司(自然人独资)",
        "有限责任公司分公司(非自然人投资或控股的法人独资)",
        "特殊普通合伙企业分支机构",
        "股份合作制",
        "股份有限公司",
        "股份有限公司(非上市)",
        "股份有限公司(非上市、国有控股)",
        "股份有限公司(非上市、自然人投资或控股)",
        "股份有限公司分公司",
        "股份有限公司分公司(上市)",
        "股份有限公司分公司(上市、国有控股)",
        "股份有限公司分公司(上市、外商投资企业投资)",
        "股份有限公司分公司(上市、自然人投资或控股)",
        "股份有限公司分公司(国有控股)",
        "股份有限公司分公司(非上市)",
        "股份有限公司分公司(非上市、自然人投资或控股)"
    ],
    [
        "",
        "内资企业",
        "农民专业合作社",
        "外商投资企业",
        "私营企业"
    ],
    [
        "",
        "交通运输、仓储和邮政业",
        "住宿和餐饮业",
        "信息传输、软件和信息技术服务业",
        "公共管理、社会保障和社会组织",
        "农、林、牧、渔业",
        "制造业",
        "卫生和社会工作",
        "居民服务、修理和其他服务业",
        "建筑业",
        "房地产业",
        "批发和零售业",
        "教育",
        "文化、体育和娱乐业",
        "水利、环境和公共设施管理业",
        "电力、热力、燃气及水生产和供应业",
        "科学研究和技术服务业",
        "租赁和商务服务业",
        "采矿业",
        "金融业"
    ],
    [
        "",
        "吊销企业",
        "在营企业",
        "注销企业",
        "迁出企业"
    ]
]
mapByVal = [
    {
        "一人有限责任公司": 1,
        "一人有限责任公司分公司": 2,
        "个人独资企业": 3,
        "个人独资企业分支机构": 4,
        "全民所有制": 5,
        "全民所有制分支机构(非法人)": 6,
        "其他有限责任公司": 7,
        "其他有限责任公司分公司": 8,
        "其他股份有限公司(非上市)": 9,
        "其他股份有限公司分公司(上市)": 10,
        "其他股份有限公司分公司(非上市)": 11,
        "内资分公司": 12,
        "农民专业合作经济组织": 13,
        "外商投资企业分公司": 14,
        "外商投资合伙企业分支机构": 15,
        "普通合伙企业": 16,
        "普通合伙企业分支机构": 17,
        "有限合伙企业": 18,
        "有限合伙企业分支机构": 19,
        "有限责任公司": 20,
        "有限责任公司(中外合资)": 21,
        "有限责任公司(台港澳与境内合资)": 22,
        "有限责任公司(台港澳合资)": 23,
        "有限责任公司(台港澳法人独资)": 24,
        "有限责任公司(台港澳自然人独资)": 25,
        "有限责任公司(国有控股)": 26,
        "有限责任公司(国有独资)": 27,
        "有限责任公司(外商投资企业与内资合资)": 28,
        "有限责任公司(外商投资企业法人独资)": 29,
        "有限责任公司(外国法人独资)": 30,
        "有限责任公司(外国自然人独资)": 31,
        "有限责任公司(自然人投资或控股)": 32,
        "有限责任公司(自然人投资或控股的法人独资)": 33,
        "有限责任公司(自然人独资)": 34,
        "有限责任公司(非自然人投资或控股的法人独资)": 35,
        "有限责任公司分公司": 36,
        "有限责任公司分公司(国有控股)": 37,
        "有限责任公司分公司(国有独资)": 38,
        "有限责任公司分公司(外商投资企业与内资合资)": 39,
        "有限责任公司分公司(外商投资企业合资)": 40,
        "有限责任公司分公司(外商投资企业投资)": 41,
        "有限责任公司分公司(外商投资企业法人独资)": 42,
        "有限责任公司分公司(自然人投资或控股)": 43,
        "有限责任公司分公司(自然人投资或控股的法人独资)": 44,
        "有限责任公司分公司(自然人独资)": 45,
        "有限责任公司分公司(非自然人投资或控股的法人独资)": 46,
        "特殊普通合伙企业分支机构": 47,
        "股份合作制": 48,
        "股份有限公司": 49,
        "股份有限公司(非上市)": 50,
        "股份有限公司(非上市、国有控股)": 51,
        "股份有限公司(非上市、自然人投资或控股)": 52,
        "股份有限公司分公司": 53,
        "股份有限公司分公司(上市)": 54,
        "股份有限公司分公司(上市、国有控股)": 55,
        "股份有限公司分公司(上市、外商投资企业投资)": 56,
        "股份有限公司分公司(上市、自然人投资或控股)": 57,
        "股份有限公司分公司(国有控股)": 58,
        "股份有限公司分公司(非上市)": 59,
        "股份有限公司分公司(非上市、自然人投资或控股)": 60
    },
    {
        "内资企业": 1,
        "农民专业合作社": 2,
        "外商投资企业": 3,
        "私营企业": 4
    },
    {
        "交通运输、仓储和邮政业": 1,
        "住宿和餐饮业": 2,
        "信息传输、软件和信息技术服务业": 3,
        "公共管理、社会保障和社会组织": 4,
        "农、林、牧、渔业": 5,
        "制造业": 6,
        "卫生和社会工作": 7,
        "居民服务、修理和其他服务业": 8,
        "建筑业": 9,
        "房地产业": 10,
        "批发和零售业": 11,
        "教育": 12,
        "文化、体育和娱乐业": 13,
        "水利、环境和公共设施管理业": 14,
        "电力、热力、燃气及水生产和供应业": 15,
        "科学研究和技术服务业": 16,
        "租赁和商务服务业": 17,
        "采矿业": 18,
        "金融业": 19
    },
    {
        "吊销企业": 1,
        "在营企业": 2,
        "注销企业": 3,
        "迁出企业": 4
    }
]


def unpackageMap(m):
    d = {}
    for field in m:
        if len(m[field]) > 0 and m[field] != "全部":
            d[field] = m[field]
    for field in specialField:
        if field in d and d[field] in mapByVal[fieldIndex[field]]:
            d[field] = int(mapByVal[fieldIndex[field]][d[field]])
    return d


@app.route('/filter', methods=['GET', 'POST'])
def page_filter():
    if request.method == 'GET':
        return render_template('filter.html')
    elif request.method == 'POST':
        print("signalFilter received!")
        data = request.get_json()
        print(data)
        amount = data["amount"]
        page = data["page"]
        sortby = "order by [%s]" % data["sortby"]
        constraint = unpackageMap(data["constraint"])

        if len(constraint) == 0:
            constraint = ""
        else:
            constraint = " and ".join(["[%s]='%s'" % (field, constraint[field]) for field in constraint])
            constraint = "where " + constraint
        data = {"data": [], "source": [], "current": 1, "total": 1}
        dbkit.open(dbName)
        sqlCount = "select count([企业名称]) from [聚类结果] " + constraint
        dbkit.cursor.execute(sqlCount)
        cnt = int(dbkit.cursor.fetchall()[0][0])
        nPage = math.ceil(cnt / amount)
        data["total"] = nPage
        if page is None or page == 0:
            page = 1
        if page > nPage:
            page = nPage
        data["current"] = page
        expr = "[企业名称]='%s'"
        if cnt > 0:
            sqlFetch = "select * from [聚类结果] " + constraint \
                       + " " + sortby + " limit %d offset %d" % (amount, amount * (page - 1))
            dbkit.cursor.execute(sqlFetch)
            rows = dbkit.cursor.fetchall()
            for i in range(len(rows)):
                row = rows[i]
                data["data"].append([amount * (page - 1) + i + 1] + list(row))
                data["source"].append(list(dbkit.getCells("非空字段数", expr=expr % row[0])[0][1:]))
        dbkit.close()
        for row in data["data"]:
            for i in range(2, 6):
                if row[i] is not None and row[i] != '':
                    row[i] = mapByKey[i - 2][int(row[i])]
        print("slotFilter triggering...")
        print(data)
        return jsonify(data)


@app.route('/query', methods=['GET', 'POST'])
def page_query():
    if request.method == 'GET':
        return render_template('Query.html')
    elif request.method == 'POST':
        print("signalQuery received!")
        data = request.get_json()
        print(data)
        IDs = data["entname"]
        amount = data["amount"]
        page = data["page"]
        data = {"data": [], "source": [], "current": 1, "total": 1}
        dbkit.open(dbName)
        expr = "[企业名称]='%s'"
        cnt = 0
        for ID in IDs:
            rows = dbkit.getCells("聚类结果", expr=expr % ID)
            if len(rows) > 0:
                data["data"].append([cnt + 1] + list(rows[0]))
                data["source"].append(list(dbkit.getCells("非空字段数", expr=expr % ID)[0][1:]))
                cnt += 1
        nPage = math.ceil(cnt / amount)
        data["total"] = nPage
        if page is None or page == 0:
            page = 1
        if page > nPage:
            page = nPage
        data["current"] = page
        if len(data["data"]) > 0:
            data["data"] = [data["data"][i] for i in range(amount * (page - 1), min(amount * page, cnt))]
        dbkit.close()
        for row in data["data"]:
            for i in range(2, 6):
                if row[i] is not None and row[i] != '':
                    row[i] = mapByKey[i - 2][int(row[i])]
        print("slotQuery triggering...")
        print(data)
        return jsonify(data)


@app.route('/train', methods=['GET', 'POST'])
def page_train():
    if request.method == 'GET':
        return render_template('admin.html')
    elif request.method == 'POST':
        print("signalTrain received!")
        data = request.get_json()
        print(data)
        data = {}
        dbkit.open(dbName)

        dbkit.evaluate(None)
        dbkit.train()
        dbkit.metastore("company.checkpoint")
        dbkit.executeScript("company.script")

        cells = dbkit.getCells('评估')
        for row in cells:
            data[row[0]] = list(row[1:])
        dbkit.close()
        print("slotTrain triggering...")
        print(data)
        return jsonify(data)


@app.route('/predict', methods=['GET', 'POST'])
def page_predict():
    if request.method == 'GET':
        return render_template('prediction.html')
    elif request.method == 'POST':
        print("signalPredict received!")
        data = request.get_json()
        print(data)
        d = {}
        for k in data:
            if data[k] != '':
                d[k] = data[k]
        dbkit.open(dbName)
        ID = 'predict'
        table = ""
        state = "在营"
        if "波动经历" in d:
            state = d["波动经历"]
        elif "企业吊销时间" in d:
            if "企业注销时间" in d:
                state = "吊销后注销"
            else:
                state = "吊销"
        elif "企业注销时间" in d:
            state = "注销"

        table = "聚类结果_predict"
        dbkit.copyTable(table, table[:-8])

        table = "抽查通过率等级（聚类：F、E、D、C、B、A）_predict"
        dbkit.copyTable(table, table[:-8])
        if "抽查通过率" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, 'passpercent', float(d["抽查通过率"]))
        table = "波动等级（聚类：A1、B1、C1、D1、E1、F1）_predict"
        dbkit.copyTable(table, table[:-8])
        if state == "注销" and "企业注销时间" in d and "企业创建时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["企业注销时间"]) - int(d["企业创建时间"]))
        table = "波动等级（聚类：A2、B2、C2、D2、E2、F2）_predict"
        dbkit.copyTable(table, table[:-8])
        if state == "吊销" and "企业吊销时间" in d and "企业创建时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["企业吊销时间"]) - int(d["企业创建时间"]))
        table = "波动等级（聚类：A3、B3、C3、D3、E3、F3）_predict"
        dbkit.copyTable(table, table[:-8])
        if state == "吊销后注销" and "企业吊销时间" in d and "企业创建时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["企业吊销时间"]) - int(d["企业创建时间"]))
        table = "经营年限（聚类：E、D、C、B、A）_predict"
        dbkit.copyTable(table, table[:-8])
        if "营业执照失效时间" in d and "营业执照生效时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["营业执照失效时间"]) - int(d["营业执照生效时间"]))
        table = "参保等级（聚类：C、B、A）_predict"
        dbkit.copyTable(table, table[:-8])
        if "参保种类数目" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "xzbz", int(d["参保种类数目"]))
        table = "执行标的等级（聚类：E、D、C、B、A）_predict"
        dbkit.copyTable(table, table[:-8])
        if "执行标的数目" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "enforce_amount", int(d["执行标的数目"]))
        table = "吊销等级（聚类：A2、B2、C2、D2、E2、F2）_predict"
        dbkit.copyTable(table, table[:-8])
        if state == "吊销" and "企业吊销时间" in d and "企业创建时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["企业吊销时间"]) - int(d["企业创建时间"]))
        table = "吊销等级（聚类：A3、B3、C3、D3、E3、F3）_predict"
        dbkit.copyTable(table, table[:-8])
        if state == "吊销后注销" and "企业吊销时间" in d and "企业创建时间" in d:
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", int(d["企业吊销时间"]) - int(d["企业创建时间"]))
        table = "企业商标等级（待合并）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["驰名商标", "著名商标"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, d[field])
        table = "企业技术水平（待合并）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["专精特新中小企业", "企业技术中小级别"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, d[field])
        table = "企业类型门类（待合并）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["企业(机构)类型", "行业门类", "企业类别"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, mapByVal[fieldIndex[field]][d[field]])
        table = "企业负面状态（待合并）_predict"
        dbkit.copyTable(table, table[:-8])
        dbkit.addRow(table, ID)
        field = "目前状态"
        if state in ["注销", "吊销后注销"]:
            dbkit.fillCell(table, ID, field, mapByVal[fieldIndex[field]]["注销企业"])
        elif state == "吊销":
            dbkit.fillCell(table, ID, field, mapByVal[fieldIndex[field]]["吊销企业"])
        else:
            dbkit.fillCell(table, ID, field, mapByVal[fieldIndex[field]]["在营企业"])
        table = "企业信用-信用水平（权重：信用水平）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["守合同重信用企业", "信用等级"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, d[field])
        table = "企业信用-信用危机（聚类：一般、较大、大、极大）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["行政处罚次数", "黑名单次数", "累计欠税额"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, float(d[field]))
        table = "企业稳定性-企业能力（聚类：差、较差、中等、较强、极强）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["对外投资次数", "中标次数", "商标申请次数", "软件著作权登记次数", "专利申请次数", "域名的知识产权数", "累计认缴额"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, float(d[field]))
        if "累计实缴额" in d and "累计认缴额" in d and 0 < float(d["累计认缴额"]) <= float(d["累计实缴额"]):
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "累计实缴百分比", float(d["累计认缴额"]) / float(d["累计实缴额"]))
        table = "企业规模背景-企业年龄（聚类：中等、较长、长、极长）_predict"
        dbkit.copyTable(table, table[:-8])
        if "企业创建时间" in d:
            t0 = int(d["企业创建时间"])
            t1 = int(d["企业吊销时间"]) if "企业吊销时间" in d else math.inf
            t2 = int(d["企业注销时间"]) if "企业注销时间" in d else math.inf
            t3 = 1576204500000
            dt = min([t1, t2, t3]) - t0
            if dt < 0:
                dt = 0
            dbkit.addRow(table, ID)
            dbkit.fillCell(table, ID, "存续时间", dt)
        table = "企业规模背景-企业规模（聚类：微小、较小、小、中等、较大）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["注册资本", "从业人数", "分支机构数", "网店个数", "招聘记录总条数"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, float(d[field]))
        table = "企业风险-司法风险（聚类：一般、较大、大、极大）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["行政处罚次数", "黑名单次数"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, float(d[field]))
        table = "企业风险-经营风险（聚类：一般、较大、大、极大）_predict"
        dbkit.copyTable(table, table[:-8])
        fields = ["行政处罚次数", "累计欠税额", "异常次数", "出质股权次数", "变更次数"]
        for field in fields:
            if field in d:
                dbkit.addRow(table, ID)
                dbkit.fillCell(table, ID, field, float(d[field]))
        dbkit.db.commit()

        dbkit.predict()
        dbkit.metastore("company.checkpoint")
        dbkit.executeScript("company.script")
        data = list(dbkit.getCells("聚类结果_predict")[0][1:])
        dbkit.close()
        print(data)
        for i in range(4):
            if data[i] is not None and data[i] != '':
                data[i] = mapByKey[i][int(data[i])]
        print("slotPredict triggering...")
        print(data)
        return jsonify(data)


if __name__ == '__main__':
    app.run()
